use std::sync::Arc;

use actix_web::{post, web::ServiceConfig, HttpRequest, Scope};
use serde::{Deserialize, Serialize};

use crate::{
    error::new_err,
    server::web::{
        codec::{new_ok, Cbor, CborRet},
        session::update_session,
    },
    store::user::{do_login, User},
    utils::{current_timestamp, pwd_md5_enc},
};

#[derive(Debug, Deserialize)]
struct LoginReq {
    account: String,
    pwd: String,
}

#[derive(Debug, Serialize)]
struct LoginRes {
    user: Arc<User>,
    token: String,
}

#[post("/login")]
async fn on_login(req: Cbor<LoginReq>, r: HttpRequest) -> CborRet<LoginRes> {
    let user = do_login(&req.account, &req.pwd).await?;
    let user = Arc::new(user);
    let addr = r.peer_addr().ok_or(new_err("invalid request"))?.to_string();
    let token = pwd_md5_enc(&format!("{}{}{}", user.account, addr, current_timestamp()));
    let res = LoginRes {
        user: user.clone(),
        token: token.clone(),
    };
    update_session(token, user);

    new_ok(res)
}

pub fn register(cfg: &mut ServiceConfig) {
    let scope = Scope::new("user").service(on_login);
    cfg.service(scope);
}
